package com.web.farme;

import com.web.farme.annotation.Table;
import com.web.farme.component.DatabaseHandler;
import com.web.farme.config.DataSourceConfig;
import com.web.farme.config.NormalAutoCreateInfo;
import com.web.farme.meta.ColumnMetadata;
import com.web.farme.meta.TableFieldInfo;
import com.web.farme.meta.TableInfo;
import com.web.farme.tool.ClassUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MysqlAutoCreate {

    private List<Object> autoCreateInfoList;

    private final DatabaseHandler databaseHandler;

    public void setAutoCreateInfoList(List<Object> autoCreateInfoList) {
        this.autoCreateInfoList = autoCreateInfoList;
    }

    @PostConstruct
    public void autoCreate() throws SQLException {
        if (autoCreateInfoList == null) {
            return;
        }
        for (Object autoCreateInfo : autoCreateInfoList) {
            if (autoCreateInfo instanceof NormalAutoCreateInfo) {
                this.handleNormalAutoCreate((NormalAutoCreateInfo) autoCreateInfo);
            }

        }
    }

    public void handleNormalAutoCreate(NormalAutoCreateInfo normalAutoCreateInfo) throws SQLException {
        DataSourceConfig dataSourceConfig = normalAutoCreateInfo.getDataSourceConfig();
        if(dataSourceConfig == null){
            return;
        }
        //设置表信息
        List<TableInfo> tableInfoList = new ArrayList<>();
        for (String scanEntityPackage : normalAutoCreateInfo.getScanEntityPackages().replaceAll("[\\s]+", "").split(",")) {
            Set<String> classSet = ClassUtils.getClassName(scanEntityPackage, true);
            for (String className : classSet) {
                try {
                    Class<?> entity = Class.forName(className);
                    if (!entity.isAnnotationPresent(Table.class)) {
                        continue;
                    }
                    TableInfo tableInfo = new TableInfo(entity);
                    tableInfo.tableHandle();
                    tableInfo.setAuto(entity.getAnnotation(Table.class).auto());
                    tableInfoList.add(tableInfo);
                } catch (ClassNotFoundException e) {
                    log.warn(className + "is not exist.");
                }
            }
        }
        try (Connection connection = DriverManager.getConnection(dataSourceConfig.getUrl(), dataSourceConfig.getUsername(), dataSourceConfig.getPassword())) {
            for (TableInfo tableInfo : tableInfoList) {
                if ("none".equals(tableInfo.getAuto())) {
                    continue;
                }
                //判断表是否存在
                String tableName = tableInfo.getTableName();
                boolean isExist = this.databaseHandler.tableIsExist(connection, tableName);
                log.info("表" + tableName + (isExist ? "存在" : "不存在"));
                if (!isExist) {
                    this.databaseHandler.createTable(connection, tableInfo);
                }
                Map<String, ColumnMetadata> columnMetadataMap = this.databaseHandler.getColumnMetaData(connection, tableName);
                for (TableFieldInfo tableFieldInfo : tableInfo.getTableFieldInfos().values()) {
                    String columnName = tableFieldInfo.getColumnName().toLowerCase();
                    if (columnMetadataMap.containsKey(columnName)) {
                        this.databaseHandler.modifyColumn(connection, columnMetadataMap.get(columnName), tableFieldInfo, tableName);
                    } else {
                        this.databaseHandler.addColumn(connection, tableFieldInfo, tableName);
                    }
                }
                this.databaseHandler.handleIndex(connection, tableInfo);
            }
        }

    }
}
